package com.fone.player.storage.download;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import com.fone.player.entity.OfflineCache;
import com.fone.player.entity.OfflineCacheFragment;
import com.fone.player.storage.OfflineCacheFileDataBaseAdapter;
import com.fone.player.storage.OfflineCacheModule;
import com.fone.player.storage.StorageModule;
import com.fone.player.util.L;

/**
 * 
 * 离线缓存下载
 * 
 * @author wangyang
 * @since 2014-8-12
 */
public class DownloadOfflineCacheRunnable implements Runnable {
	private static final String TAG = DownloadOfflineCacheRunnable.class
			.getSimpleName();
	/**
	 * 连接超时10秒
	 */
	private static final int CONNECT_TIME_OUT = 10 * 1000;
	/**
	 * 读取超时30秒
	 */
	private static final int READ_TIME_OUT = 30 * 1000;
	/**
	 * 碎片重试次数
	 */
	private static final int FRAGMENT_MAX_TIME = 3;
	/**
	 * 视频重试次数
	 */
	private static final int FILE_MAX_TIME = 3;
	/**
	 * 任务运行中
	 */
	public static final int STATE_RUNNING = 1;
	/**
	 * 任务已停止
	 */
	public static final int STATE_STOP = 2;
	/**
	 * 任务完成
	 */
	public static final int STATE_FINISH = 3;
	/**
	 * 运行任务
	 */
	public static final int OPERATE_RUNNING = 1;
	/**
	 * 停止任务
	 */
	public static final int OPERATE_STOP = 2;
	/**
	 * 批量停止任务(更新状态)
	 */
	public static final int OPERATE_STOP_BATCH_UPDATE_STATE = 3;
	/**
	 * 批量停止任务(不更新状态)
	 */
	public static final int OPERATE_STOP_BATCH_UNUPDATE_STATE = 4;
	/**
	 * 停止任务并删除相关文件
	 */
	public static final int OPERATE_DELETE = 5;

	// 存储当前连接的所有对象
	private LinkedHashMap<String, HttpGet> mHttpGetHashMap = new LinkedHashMap<String, HttpGet>();
	private OfflineCache mOfflineCache = null;
	private Handler mHandler = null;
	// 任务状态
	private int mRunnableState = STATE_STOP;
	// 操作类型
	private int mOperateType = OPERATE_STOP;
	// 当前分片重试次数
	private int mCurrentFragmentTime = 0;
	// 当前视频重试次数
	private int mCurrentFileTime = 0;

	/**
	 * 
	 * 设置任务执行方式
	 * 
	 * @param operateState
	 *            执行类型
	 * @return void
	 */
	public void setOperateType(int operateType) {

		mOperateType = operateType;

		Iterator<Entry<String, HttpGet>> iterator = mHttpGetHashMap.entrySet()
				.iterator();
		while (iterator.hasNext()) {
			Entry<String, HttpGet> entry = iterator.next();
			HttpGet httpGet = entry.getValue();
			if (httpGet != null && !httpGet.isAborted()) {
				L.v(TAG, "setOperateType", "abort");
				httpGet.abort();
			}
		}
		Message msg = new Message();
		Bundle bundle = new Bundle();
		bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
		msg.setData(bundle);
		msg.what = StorageModule.MSG_DOWNLOAD_SUCCESS;
		mHandler.sendMessage(msg);
	}

	/**
	 * 
	 * 获取任务状态
	 * 
	 * @param runnableState
	 *            任务状态
	 * @return void
	 */
	public int getRunnableState() {

		return mRunnableState;
	}

	public void setOfflineCache(OfflineCache offlineCache) {
		mOfflineCache = offlineCache;
	}

	public OfflineCache getOfflineCache() {
		return mOfflineCache;
	}

	public void setHandler(Handler handler) {
		mHandler = handler;
	}

	@Override
	public void run() {

		// 任务运行
		mRunnableState = STATE_RUNNING;
		L.v(TAG,
				"run",
				"mRunnableState=STATE_RUNNING name="
						+ mOfflineCache.getCacheName()
						+ mOfflineCache.getCacheEpisodeNum());

		// 下载视频
		limitSpeedDownloadFile();

		// 任务停止
		mRunnableState = STATE_STOP;
		L.v(TAG,
				"run",
				"mRunnableState=STATE_STOP name="
						+ mOfflineCache.getCacheName()
						+ mOfflineCache.getCacheEpisodeNum());

	}

	/**
	 * 
	 * 限速下载文件
	 * 
	 * @param speed
	 *            每秒允许下载的字节数(0代表不限速)
	 * @return void
	 */
	public void limitSpeedDownloadFile() {

		L.v(TAG, "limitSpeedDownloadFile", "start");

		mOfflineCache
				.setCacheDownloadState(OfflineCache.CACHE_STATE_DOWNLOADING);
		// 更新数据库
		OfflineCacheFileDataBaseAdapter.getInstance().updateOfflineCacheFile(
				mOfflineCache);
		L.v(TAG,
				"limitSpeedDownloadFile",
				"send downloadState=CACHE_STATE_DOWNLOADING name="
						+ mOfflineCache.getCacheName()
						+ mOfflineCache.getCacheEpisodeNum());
		// 发送通知
		Message msg = new Message();
		Bundle bundle = new Bundle();
		bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
		msg.setData(bundle);
		msg.what = StorageModule.MSG_DOWNLOAD_PROGRESS;
		mHandler.sendMessage(msg);

		// 读取上一次进度
		SaveCacheDataUtil.getInstance().getFilePathByOfflineCacheProgress(
				mOfflineCache);

		// 解析报文
		mOfflineCache = CacheMessageHelper.getInstance().parseXYZPlayUrl(
				mOfflineCache);

		// 记录视频信息和分片信息
		SaveCacheDataUtil.getInstance().saveCacheJSONFile(mOfflineCache);

		switch (mOfflineCache.getCacheDownloadState()) {
		case OfflineCache.CACHE_STATE_ERROR:
			// 解析出错
			L.e(TAG, "run", "CACHE_STATE_ERROR");

			// 更新数据库
			OfflineCacheFileDataBaseAdapter.getInstance()
					.updateOfflineCacheFile(mOfflineCache);

			// 更新UI
			msg = new Message();
			bundle = new Bundle();
			bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
			msg.setData(bundle);
			msg.what = StorageModule.MSG_DOWNLOAD_ERROR;
			mHandler.sendMessage(msg);

			break;
		default:

			// 获取分片集合
			LinkedList<OfflineCacheFragment> offlineCacheFragmentLinkedList = mOfflineCache
					.getOfflineCacheFragmentLinkedList();

			if (offlineCacheFragmentLinkedList.size() == 0) {
				L.e(TAG, "run",
						"no frag list,offlineCacheFragmentLinkedList.size=0");
				return;
			}

			// 计算分片长度
			calculateFragmentLength(offlineCacheFragmentLinkedList);

			// 下载分片
			limitSpeedDownloadFragmentList(0, offlineCacheFragmentLinkedList);

			// 判断任务状态
			switch (mRunnableState) {
			case STATE_FINISH:

				L.v(TAG, "limitSpeedDownloadFile",
						"send mRunnableState=STATE_FINISH downloadState="
								+ mOfflineCache.getCacheDownloadState());

				mOfflineCache
						.setCacheDownloadState(OfflineCache.CACHE_STATE_FINISH);
				msg = new Message();
				bundle = new Bundle();
				bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
				msg.setData(bundle);
				msg.what = StorageModule.MSG_DOWNLOAD_SUCCESS;
				mHandler.sendMessage(msg);
				break;
			case STATE_STOP:

				L.v(TAG, "limitSpeedDownloadFile",
						"send mRunnableState=STATE_STOP downloadState="
								+ mOfflineCache.getCacheDownloadState());

				msg = new Message();
				bundle = new Bundle();
				bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
				msg.setData(bundle);
				msg.what = StorageModule.MSG_DOWNLOAD_SUCCESS;
				mHandler.sendMessage(msg);

				// 判断操作状态
				switch (mOperateType) {
				case OPERATE_STOP:
					break;
				default:
					break;
				}
				break;
			default:
				break;
			}

			// 下载结束(可能失败,可能成功),单个更新数据库,批量更新放在外面做
			OfflineCacheFileDataBaseAdapter.getInstance()
					.updateOfflineCacheFile(mOfflineCache);

			break;
		}

	}

	/**
	 * 
	 * 限速下载分片集合
	 * 
	 * @param speed
	 *            每秒允许下载的字节数(0代表不限速)
	 * @param offlineCacheFragmentLinkedList
	 *            分片信息
	 * @return void
	 */
	public void limitSpeedDownloadFragmentList(long speed,
			LinkedList<OfflineCacheFragment> offlineCacheFragmentLinkedList) {

		// 取当前队列第一个分片
		OfflineCacheFragment offlineCacheFragment = offlineCacheFragmentLinkedList
				.removeFirst();

		L.v(TAG, "limitSpeedDownloadFragment", "start url="
				+ offlineCacheFragment.getCacheFragmentUrl());

		// 读取流信息
		int errorCode = limitSpeedDownloadFragment(speed, offlineCacheFragment);

		// 判断结果
		switch (errorCode) {
		case OfflineCache.CACHE_ERROR_CODE_SUCCESS:
			long alreadySize = offlineCacheFragment.getCacheAlreadySize();
			long totalSize = offlineCacheFragment.getCacheTotalSize();
			if (alreadySize == totalSize) {

				L.v(TAG, "limitSpeedDownloadFragment",
						"DOWNLOAD_STATE_FINISH fragmentUrl="
								+ offlineCacheFragment.getCacheFragmentUrl());
				offlineCacheFragment.setCacheAlreadySize(offlineCacheFragment
						.getCacheTotalSize());
				offlineCacheFragment
						.setCacheDownloadState(OfflineCache.CACHE_STATE_FINISH);
				mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);

				// 记录视频信息和分片信息
				SaveCacheDataUtil.getInstance()
						.saveCacheJSONFile(mOfflineCache);

				if (offlineCacheFragmentLinkedList.size() == 0) {

					// 分片列表最后一个分片下载完毕
					L.v(TAG, "limitSpeedDownloadFragment",
							"already download finished last frag,offlineCacheFragmentLinkedList.size=0");
					mRunnableState = STATE_FINISH;

				} else {

					// 下载下一个分片
					limitSpeedDownloadFragmentList(0,
							offlineCacheFragmentLinkedList);

				}
			}
			break;
		case OfflineCache.CACHE_ERROR_CODE_USER_OPERATE:

			mRunnableState = STATE_STOP;

			switch (mOperateType) {
			case OPERATE_STOP:
			case OPERATE_STOP_BATCH_UPDATE_STATE:
				L.v(TAG, "limitSpeedDownloadFragment",
						"CACHE_STATE_PAUSE OPERATE_STOP_BATCH_UPDATE_STATE fragmentUrl="
								+ offlineCacheFragment.getCacheFragmentUrl());
				offlineCacheFragment
						.setCacheDownloadState(OfflineCache.CACHE_STATE_PAUSE);
				mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);
				mOfflineCache
						.setCacheDownloadState(OfflineCache.CACHE_STATE_PAUSE);

				// 记录视频信息和分片信息
				SaveCacheDataUtil.getInstance()
						.saveCacheJSONFile(mOfflineCache);
				break;
			case OPERATE_STOP_BATCH_UNUPDATE_STATE:
				L.v(TAG, "limitSpeedDownloadFragment",
						"CACHE_STATE_PAUSE OPERATE_STOP_BATCH_UNUPDATE_STATE fragmentUrl="
								+ offlineCacheFragment.getCacheFragmentUrl());

				// 记录视频信息和分片信息
				SaveCacheDataUtil.getInstance()
						.saveCacheJSONFile(mOfflineCache);
				break;
			case OPERATE_DELETE:

				// 删除文件
				OfflineCacheModule.getInstance().deleteOfflineCacheFile(
						mOfflineCache);

				break;
			default:
				break;
			}
			break;
		case OfflineCache.CACHE_ERROR_CODE_NOT_WRITE:
		case OfflineCache.CACHE_ERROR_CODE_MALFORMED_URL:
		case OfflineCache.CACHE_ERROR_CODE_TIMEOUT:
		case OfflineCache.CACHE_ERROR_CODE_IO:
		case OfflineCache.CACHE_ERROR_CODE_CONNECTION_REFUSED:
		case OfflineCache.CACHE_ERROR_CODE_MESSAGE_PARSE_FAIL:
		case OfflineCache.CACHE_ERROR_CODE_FRAGMENT_URL_NULL:
		case OfflineCache.CACHE_ERROR_CODE_FRAGMENT_URL_RESPONSE_MIME_FAIL:
		case OfflineCache.CACHE_ERROR_CODE_FRAGMENT_URL_RESPONSE_STATUS_CODE_FAIL:

			mRunnableState = STATE_STOP;

			// 记录视频信息和分片信息
			SaveCacheDataUtil.getInstance().saveCacheJSONFile(mOfflineCache);
			break;
		default:
			break;
		}

	}

	/**
	 * 
	 * 限速下载分片文件
	 * 
	 * @param speed
	 *            每秒允许下载的字节数(0代表不限速)
	 * @param offlineCacheFragment
	 *            分片信息
	 * @return void
	 */
	private int limitSpeedDownloadFragment(long speed,
			OfflineCacheFragment offlineCacheFragment) {
		int errorCode = OfflineCache.CACHE_ERROR_CODE_SUCCESS;
		Message msg = new Message();
		Bundle bundle = new Bundle();
		RandomAccessFile randomAccessFile = null;
		BufferedInputStream bufferedInputStream = null;
		long length = 0;
		try {
			// 请求真实文件
			File file = new File(
					offlineCacheFragment.getCacheFragmentStoragePath());

			if (!file.exists()) {

				L.v(TAG, "limitSpeedDownloadFragment", "create new file path="
						+ offlineCacheFragment.getCacheFragmentStoragePath());

				file.createNewFile();

				// 文件被删除,更新进度为0
				offlineCacheFragment.setCacheAlreadySize(0);

			} else {

				// FIXME 判断片数和当前片的大小是否和上次一样,如果一样,就继续下载,否则就删除已下载的文件

				// 获得开始位置,继续下载
				offlineCacheFragment.setCacheAlreadySize(file.length());

			}
			HttpResponse response = getHttpResponse(
					offlineCacheFragment.getCacheFragmentUrl(),
					offlineCacheFragment.getCacheAlreadySize(),
					offlineCacheFragment.getCacheTotalSize());

			boolean isValidate = isValidateHttpReponse(response,
					offlineCacheFragment);
			if (!isValidate) {
				// 数据无效
				L.e(TAG, "limitSpeedDownloadFragment",
						"isValidate=" + isValidate + " url="
								+ offlineCacheFragment.getCacheFragmentUrl());
				if (mCurrentFileTime <= FILE_MAX_TIME) {

					mCurrentFileTime++;

					L.w(TAG, "limitSpeedDownloadFragment",
							"retry mCurrentFileTime=" + mCurrentFileTime);

					// 重试(重新取报文并下载)
					limitSpeedDownloadFile();

				} else {

					L.e(TAG, "limitSpeedDownloadFragment",
							"already retry FILE_MAX_TIME send MSG_DOWNLOAD_ERROR");

					// 超过规定次数,已经出错,发送出错消息
					msg = new Message();
					bundle = new Bundle();
					bundle.putParcelable(OfflineCache.OFFLINE_CACHE,
							mOfflineCache);
					msg.setData(bundle);
					msg.what = StorageModule.MSG_DOWNLOAD_ERROR;
					mHandler.sendMessage(msg);

					errorCode = offlineCacheFragment
							.getCacheFragmentErrorCode();
				}

				return errorCode;
			}

			errorCode = offlineCacheFragment.getCacheFragmentErrorCode();
			L.v(TAG, "limitSpeedDownloadFragment", "isValidate=" + isValidate
					+ " response HttpEntity");

			// 请求文件大小
			HttpEntity httpEntity = response.getEntity();

			randomAccessFile = new RandomAccessFile(file, "rws");

			randomAccessFile.seek(offlineCacheFragment.getCacheAlreadySize());
			// 开始读写数据
			bufferedInputStream = new BufferedInputStream(
					httpEntity.getContent());

			int pack = 10240; // 10K bytes
			speed = speed * 1024;// 将速度换算成字节
			// int sleep = 200; //每秒5次 即5*10K bytes每秒
			int sleep = 0;
			if (speed != 0) {
				sleep = (int) Math.floor(1000 * pack / speed) + 1;
				L.v(TAG, "limitSpeedDownloadFragment", "speed=" + speed
						+ " sleep=" + sleep + " fragmentUrl="
						+ offlineCacheFragment.getCacheFragmentUrl());
			}
			int maxCount = (int) Math.floor((length - offlineCacheFragment
					.getCacheAlreadySize()) / pack) + 1;
			L.v(TAG, "limitSpeedDownloadFragment",
					"maxCount=" + maxCount + " fragmentUrl="
							+ offlineCacheFragment.getCacheFragmentUrl());
			byte[] buf = new byte[1024 * 200];
			int currentLength;
			while ((currentLength = bufferedInputStream.read(buf)) != -1) {
				// L.v(TAG, "limitSpeedDownloadFragment", "mOperateType="
				// + mOperateType);
				switch (mOperateType) {
				case OPERATE_STOP:
				case OPERATE_STOP_BATCH_UPDATE_STATE:
				case OPERATE_STOP_BATCH_UNUPDATE_STATE:
				case OPERATE_DELETE:
					// 手动停止任务
					errorCode = OfflineCache.CACHE_ERROR_CODE_USER_OPERATE;
					mRunnableState = STATE_STOP;
					break;
				default:
					// 正常下载
					if (file.canWrite()) {
						randomAccessFile.write(buf, 0, currentLength);

						// 发送消息
						sendDownloadingMessage(offlineCacheFragment,
								currentLength);

						if (sleep != 0) {
							try {

								Thread.sleep(sleep);
								L.v(TAG,
										"limitSpeedDownloadFragment",
										"sleep="
												+ sleep
												+ " fragmentUrl="
												+ offlineCacheFragment
														.getCacheFragmentUrl());

							} catch (InterruptedException e) {
								if (e != null) {
									e.printStackTrace();
								}
							}
						}
					} else {

						L.e(TAG,
								"limitSpeedDownloadFragment",
								"DOWNLOAD_IO_EXCEPTION"
										+ " 下载失败,本地路径不能写数据  fragmentUrl="
										+ offlineCacheFragment
												.getCacheFragmentUrl());
						offlineCacheFragment
								.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
						mOfflineCache
								.addOfflineCacheFragment(offlineCacheFragment);
						mOfflineCache
								.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);

						// 不能写数据,io异常(usb存储模式)
						errorCode = OfflineCache.CACHE_ERROR_CODE_NOT_WRITE;
						mRunnableState = STATE_STOP;
						break;
					}
					break;
				}

				// 判断下载期间是否有外部操作干预
				if (errorCode != OfflineCache.CACHE_ERROR_CODE_SUCCESS) {
					break;
				}
			}

			mCurrentFragmentTime = 0;

		} catch (SocketException e) {

			switch (mOperateType) {
			case OPERATE_STOP:
			case OPERATE_STOP_BATCH_UPDATE_STATE:
			case OPERATE_STOP_BATCH_UNUPDATE_STATE:
			case OPERATE_DELETE:
				L.v(TAG, "limitSpeedDownloadFragment",
						"SocketException CACHE_ERROR_CODE_USER_OPERATE mOperateType="
								+ mOperateType);
				errorCode = OfflineCache.CACHE_ERROR_CODE_USER_OPERATE;
				break;
			default:
				L.v(TAG, "limitSpeedDownloadFragment",
						"SocketException mOperateType=" + mOperateType);
				// 正常下载
				switch (errorCode) {
				case OfflineCache.CACHE_ERROR_CODE_USER_OPERATE:
					// 忽略
					L.v(TAG, "limitSpeedDownloadFragment",
							"SocketException errorCode=CACHE_ERROR_CODE_USER_OPERATE mOperateType="
									+ mOperateType);
					break;
				default:

					// 超过规定次数就发送出错信息
					if (mCurrentFragmentTime <= FRAGMENT_MAX_TIME) {

						mCurrentFragmentTime++;

						L.w(TAG,
								"limitSpeedDownloadFragment",
								"SocketException retry time="
										+ mCurrentFragmentTime
										+ " name="
										+ mOfflineCache.getCacheName()
										+ mOfflineCache.getCacheEpisodeNum()
										+ " fragmentUrl="
										+ offlineCacheFragment
												.getCacheFragmentUrl());

						limitSpeedDownloadFragment(speed, offlineCacheFragment);

					} else {

						L.e(TAG,
								"limitSpeedDownloadFragment",
								"SocketException name="
										+ mOfflineCache.getCacheName()
										+ mOfflineCache.getCacheEpisodeNum()
										+ " fragmentUrl="
										+ offlineCacheFragment
												.getCacheFragmentUrl());

						errorCode = OfflineCache.CACHE_ERROR_CODE_TIMEOUT;

						if (DownloadUtil.getInstance().isNetwork()) {

							// 本地有网,url下载出错,标记成出错
							offlineCacheFragment
									.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
							mOfflineCache
									.addOfflineCacheFragment(offlineCacheFragment);
							mOfflineCache
									.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);

						} else {

							// 本地无网,url下载出错,标记成等待
							offlineCacheFragment
									.setCacheDownloadState(OfflineCache.CACHE_STATE_WAITING);
							mOfflineCache
									.addOfflineCacheFragment(offlineCacheFragment);
							mOfflineCache
									.setCacheDownloadState(OfflineCache.CACHE_STATE_WAITING);

						}
					}

					break;
				}
				break;
			}

		} catch (SocketTimeoutException e) {

			// 超过规定次数就发送出错信息
			if (mCurrentFragmentTime <= FRAGMENT_MAX_TIME) {

				mCurrentFragmentTime++;

				L.w(TAG,
						"limitSpeedDownloadFragment",
						"SocketTimeoutException retry time="
								+ mCurrentFragmentTime + " name="
								+ mOfflineCache.getCacheName()
								+ mOfflineCache.getCacheEpisodeNum()
								+ " fragmentUrl="
								+ offlineCacheFragment.getCacheFragmentUrl());

				limitSpeedDownloadFragment(speed, offlineCacheFragment);

			} else {

				L.e(TAG,
						"limitSpeedDownloadFragment",
						"SocketTimeoutException name="
								+ mOfflineCache.getCacheName()
								+ mOfflineCache.getCacheEpisodeNum()
								+ " fragmentUrl="
								+ offlineCacheFragment.getCacheFragmentUrl());

				errorCode = OfflineCache.CACHE_ERROR_CODE_TIMEOUT;
				offlineCacheFragment
						.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
				mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);
				mOfflineCache
						.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
			}

		} catch (MalformedURLException e) {
			if (e != null) {
				e.printStackTrace();
				mOfflineCache.setCacheErrorMessage(mOfflineCache.getCacheName()
						+ mOfflineCache.getCacheEpisodeNum() + " "
						+ e.getMessage() + " fragmentUrl="
						+ offlineCacheFragment.getCacheFragmentUrl());
			}
			L.e(TAG,
					"limitSpeedDownloadFragment",
					"MalformedURLException " + mOfflineCache.getCacheName()
							+ mOfflineCache.getCacheEpisodeNum()
							+ " fragmentUrl="
							+ offlineCacheFragment.getCacheFragmentUrl());
			errorCode = OfflineCache.CACHE_ERROR_CODE_MALFORMED_URL;
			offlineCacheFragment
					.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
			mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);
			mOfflineCache.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
			msg = new Message();
			bundle = new Bundle();
			bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
			msg.setData(bundle);
			msg.what = StorageModule.MSG_DOWNLOAD_ERROR;
			mHandler.sendMessage(msg);

			// 记录视频信息和分片信息
			SaveCacheDataUtil.getInstance().saveCacheJSONFile(mOfflineCache);

		} catch (IOException e) {
			if (e != null) {
				e.printStackTrace();
				mOfflineCache.setCacheErrorMessage(mOfflineCache.getCacheName()
						+ mOfflineCache.getCacheEpisodeNum() + " "
						+ e.getMessage() + " fragmentUrl="
						+ offlineCacheFragment.getCacheFragmentUrl());
			}
			L.e(TAG,
					"limitSpeedDownloadFragment",
					"exception=" + e + " name=" + mOfflineCache.getCacheName()
							+ mOfflineCache.getCacheEpisodeNum()
							+ " fragmentUrl="
							+ offlineCacheFragment.getCacheFragmentUrl());
			errorCode = OfflineCache.CACHE_ERROR_CODE_IO;
			mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);
			offlineCacheFragment
					.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
			mOfflineCache.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
			msg = new Message();
			bundle = new Bundle();
			bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
			msg.setData(bundle);
			msg.what = StorageModule.MSG_DOWNLOAD_ERROR;
			mHandler.sendMessage(msg);
			// 记录视频信息和分片信息
			SaveCacheDataUtil.getInstance().saveCacheJSONFile(mOfflineCache);

		} finally {

			// 释放资源
			release(bufferedInputStream, randomAccessFile);

		}
		return errorCode;
	}

	/**
	 * 
	 * 发送下载中的消息
	 * 
	 * @param offlineCacheFragment
	 *            分片信息
	 * @param currentLength
	 *            当前下载的大小
	 * @return void
	 */
	private void sendDownloadingMessage(
			OfflineCacheFragment offlineCacheFragment, int currentLength) {
		offlineCacheFragment
				.setCacheDownloadState(OfflineCache.CACHE_STATE_DOWNLOADING);
		offlineCacheFragment.addCacheAlreadySize(currentLength);
		mOfflineCache
				.setCacheDownloadState(OfflineCache.CACHE_STATE_DOWNLOADING);
		mOfflineCache.addCacheAlreadySize(currentLength);
		mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);

		SaveCacheDataUtil.getInstance().saveCacheJSONFile(mOfflineCache);

		// L.v(TAG, "limitSpeedDownloadFragment", "percentNum="
		// + offlineCacheFragment.getCachePercentNum() + " alreadySize="
		// + offlineCacheFragment.getCacheAlreadySize() + " totalSize="
		// + offlineCacheFragment.getCacheTotalSize() + " url="
		// + offlineCacheFragment.getCacheFragmentUrl());

		Message msg = new Message();
		Bundle bundle = new Bundle();
		bundle.putParcelable(OfflineCache.OFFLINE_CACHE, mOfflineCache);
		bundle.putLong(OfflineCache.OFFLINE_CACHE_CURRENT_SIZE, currentLength);
		msg.setData(bundle);
		msg.what = StorageModule.MSG_DOWNLOAD_PROGRESS;
		mHandler.sendMessage(msg);
	}

	private void release(BufferedInputStream bufferedInputStream,
			RandomAccessFile randomAccessFile) {
		L.v(TAG, "release", "start randomAccessFile=" + randomAccessFile);

		if (bufferedInputStream != null) {
			try {
				L.v(TAG, "release", "bufferedInputStream close");
				bufferedInputStream.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}

		if (randomAccessFile != null) {
			try {
				L.v(TAG, "release", "randomAccessFile close");
				randomAccessFile.close();
				randomAccessFile = null;
			} catch (IOException e) {
				if (e != null) {
					e.printStackTrace();
				}
			}
		}

	}

	/**
	 * 
	 * 计算分片长度
	 * 
	 * @param offlineCacheFragmentLinkedList
	 *            分片集合
	 * @return void
	 */
	private void calculateFragmentLength(
			LinkedList<OfflineCacheFragment> offlineCacheFragmentLinkedList) {

		mOfflineCache.setCacheTotalSize(0);

		for (OfflineCacheFragment offlineCacheFragment : offlineCacheFragmentLinkedList) {

			if (offlineCacheFragment.getCacheTotalSize() == 0) {
				HttpResponse response = getHttpResponse(
						offlineCacheFragment.getCacheFragmentUrl(), 0, 0);
				boolean isValidate = isValidateHttpReponse(response,
						offlineCacheFragment);

				if (isValidate) {

					// 请求文件大小
					HttpEntity entity = response.getEntity();
					long fragmentLength = entity.getContentLength();
					L.v(TAG, "calculateFragmentLength", "length="
							+ fragmentLength);
					offlineCacheFragment.setCacheTotalSize(fragmentLength);
					mOfflineCache.addCacheTotalSize(fragmentLength);

				} else {

					L.e(TAG,
							"calculateFragmentLength",
							"isValidate="
									+ isValidate
									+ " url="
									+ offlineCacheFragment
											.getCacheFragmentUrl());
					// 数据无效
					break;
				}

			}

		}
	}

	/**
	 * 
	 * 验证请求是否有效
	 * 
	 * @param httpResponse
	 *            相应流
	 * @param offlineCacheFragment
	 *            分片信息
	 * @return boolean 是否有效
	 */
	private boolean isValidateHttpReponse(HttpResponse httpResponse,
			OfflineCacheFragment offlineCacheFragment) {
		boolean isValidate = false;
		L.v(TAG, "isValidateHttpReponse", "start");
		if (httpResponse == null) {
			L.e(TAG,
					"isValidateHttpReponse",
					"httpResponse=null name=" + mOfflineCache.getCacheName()
							+ mOfflineCache.getCacheEpisodeNum()
							+ " fragmentUrl="
							+ offlineCacheFragment.getCacheFragmentUrl());
			isValidate = false;
			offlineCacheFragment
					.setCacheFragmentErrorCode(OfflineCache.CACHE_ERROR_CODE_CONNECTION_REFUSED);
		} else {

			int responseCode = httpResponse.getStatusLine().getStatusCode();
			// rf2616协议
			switch (responseCode) {
			case HttpStatus.SC_OK:
			case HttpStatus.SC_PARTIAL_CONTENT:
				// 请求成功
				isValidate = true;

				// 判断内容是否合法
				if (httpResponse.getFirstHeader("Content-Type") != null
						&& httpResponse.getFirstHeader("Content-Type")
								.getValue().contains("text/html")) {
					L.v(TAG, "Content-Type", " not contains text/html ");
					try {
						L.e(TAG,
								"isValidateHttpReponse",
								"responseCode="
										+ responseCode
										+ " content="
										+ httpResponse.getEntity().getContent()
										+ " fragmentUrl="
										+ offlineCacheFragment
												.getCacheFragmentUrl());
					} catch (IllegalStateException e) {
						if (e != null) {
							e.printStackTrace();
						}
					} catch (IOException e) {
						if (e != null) {
							e.printStackTrace();
						}
					}
					offlineCacheFragment
							.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
					mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);
					offlineCacheFragment
							.setCacheFragmentErrorCode(OfflineCache.CACHE_ERROR_CODE_FRAGMENT_URL_RESPONSE_MIME_FAIL);
					isValidate = false;
				}
				break;
			default:
				// 请求失败
				L.e(TAG,
						"isValidateHttpReponse",
						"responseCode=" + responseCode + " name="
								+ mOfflineCache.getCacheName()
								+ mOfflineCache.getCacheEpisodeNum()
								+ " fragmentUrl="
								+ offlineCacheFragment.getCacheFragmentUrl());
				StorageModule.getInstance().writeStackTrace();
				isValidate = false;
				offlineCacheFragment
						.setCacheFragmentErrorCode(OfflineCache.CACHE_ERROR_CODE_FRAGMENT_URL_RESPONSE_STATUS_CODE_FAIL);
				break;
			}
		}
		// 发送消息
		if (!isValidate) {

			offlineCacheFragment
					.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
			mOfflineCache.addOfflineCacheFragment(offlineCacheFragment);
			mOfflineCache.setCacheDownloadState(OfflineCache.CACHE_STATE_ERROR);
			// 记录视频信息和分片信息
			SaveCacheDataUtil.getInstance().saveCacheJSONFile(mOfflineCache);

		}
		return isValidate;
	}

	private HttpResponse getHttpResponse(String fragmentUrl, long alreadySize,
			long totalSize) {

		HttpParams baseParams = new BasicHttpParams();
		// 设置超时时间
		HttpConnectionParams.setConnectionTimeout(baseParams, CONNECT_TIME_OUT);
		HttpConnectionParams.setSoTimeout(baseParams, READ_TIME_OUT);
		// 设置google user agent(也可以设置其他的,看具体情况)
		String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13";
		HttpProtocolParams.setUserAgent(baseParams, userAgent);
		DefaultHttpClient httpClient = new DefaultHttpClient(baseParams);
		HttpGet httpGet = new HttpGet(fragmentUrl);

		if (alreadySize > 0 && totalSize > 0) {
			// 获取指定位置的数据，Range范围如果超出服务器上数据范围, 会以服务器数据末尾为准
			httpGet.addHeader("Range", "bytes=" + alreadySize + "-" + totalSize);
		}
		// 防止length=0
		// httpGet.addHeader("Accept-Encoding", "identity");
		HttpResponse response = null;
		try {

			response = httpClient.execute(httpGet);

			// 保存连接对象
			mHttpGetHashMap.put(fragmentUrl, httpGet);

			mCurrentFragmentTime = 0;

		} catch (ConnectTimeoutException e) {
			if (e != null) {
				e.printStackTrace();
			}

		} catch (SocketTimeoutException e) {
			if (e != null) {
				e.printStackTrace();
			}

			// 超过规定次数就发送出错信息
			if (mCurrentFragmentTime <= FRAGMENT_MAX_TIME) {

				mCurrentFragmentTime++;

				L.w(TAG, "getHttpResponse",
						"SocketTimeoutException,retry mCurrentFragmentTime="
								+ mCurrentFragmentTime);

				getHttpResponse(fragmentUrl, alreadySize, totalSize);
			} else {

				L.e(TAG, "getHttpResponse",
						"SocketTimeoutException,already retry FRAGMENT_MAX_TIME");

			}

		} catch (ClientProtocolException e) {
			if (e != null) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			if (e != null) {
				e.printStackTrace();
			}

		}
		return response;
	}
}
